#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <arpa/inet.h>
#include <event2/event.h>
#include <event2/listener.h>
#include <event2/event.h>
#include "libevent_http.h"
#include "zhttp.h"

int main(int argc, char const *argv[])
{
    if(argc < 3){
        printf("eg: ./epoll_http port path\n");
        exit(-1);
    }
    //端口
    int port = atoi(argv[1]);
    //修改进程的工作目录,方便后续操作
    int ret = chdir(argv[2]);
    if(ret == -1){
        printf("dir is not exits: %s\n", argv[2]);
        perror("chdir error");
        exit(-1);
    }
    //启动libevent模型
    struct event_base* base = NULL;
    struct sockaddr_in serv;
    struct evconnlistener* listener = NULL; 
    struct event* signal_event = NULL;
    struct zhttp* zhp = NULL;

    base = event_base_new();
    if(!base){
        fprintf(stderr, "event_base_new failed!\n");
        goto __ERROR;
    }

    zhp = zhttp_new(base);
    if(!zhp){
        fprintf(stderr, "zhttp_new failed!\n");
        goto __ERROR;
    }

    memset(&serv, 0, sizeof(serv));
    serv.sin_family = AF_INET;
    serv.sin_port = htons(port);

    //创建监听的套接字,绑定,监听,接受连接请求
    listener = evconnlistener_new_bind(base, listener_cb, (void *)zhp, 
                                LEV_OPT_REUSEABLE | LEV_OPT_CLOSE_ON_FREE,-1,
                                (struct sockaddr *)&serv, sizeof(serv));
    if(!listener){
        fprintf(stderr, "evconnlistener_new_bind failed!\n");
        goto __ERROR;
    }

    //创建信号事件,捕捉处理
    signal_event =  evsignal_new(base, SIGINT, signal_cb, (void *)base);
    // if(!signal_event ||  event_add(signal_event, NULL) < 0){
    //     fprintf(stderr, "evsignal_new add a signal event!\n");
    //     goto __ERROR;
    // }

    //事件循环
    event_base_dispatch(base);

__ERROR:
    if(listen){
        evconnlistener_free(listener);
    }
    if(signal_event){
        event_free(signal_event);
    }
    if(base){
        event_base_free(base);
    }
    if(zhp){
        zhttp_free(zhp);
    }
    printf("done\n");
    return 0;
}
